package com.asen.commons.utils;

import com.asen.commons.enums.CacheTypeEnum;
import com.asen.commons.core.base.domain.Core;
import com.asen.commons.cache.CacheDataManager;
import com.asen.commons.cache.RedisCache;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 缓存工具类
 *
 * @author Gary
 * @version 1.0
 * @date 2018-12-21
 */
public class CacheUtils {

    /**
     * 获取对象
     *
     * @param modelClazz
     * @param id
     * @return
     */
    public static <T> T getObjectVo(Class<T> modelClazz, Long id) {
        if (id == null || modelClazz == null) {
            return null;
        }

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getObject(modelClazz, id);
    }

    /**
     * 获取对象
     *
     * @param modelClass
     * @param id
     * @return
     */
    public static <T> T getObjectVo(String modelClass, Long id) {
        if (id == null || StringUtils.isBlank(modelClass)) {
            return null;
        }
        Class<T> modelClazz = null;
        try {
            modelClazz = (Class<T>) Class.forName(modelClass);
        } catch (Exception e) {
        }
        return getObjectVo(modelClazz, id);
    }

    public static <T> Collection<T> getList(Class<T> modelClazz) {
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        if (redisCache == null) {
            return null;
        }

        String key = new StringBuilder(modelClazz.getName()).append(CacheDataManager.CACHE_KEY_OBJECT_SPLIT).toString();
        Map<Object, Object> map = redisCache.getHashAll(CacheTypeEnum.BAS_DATA.getValue(), key);
        if (map == null) {
            return null;
        }

        return (Collection<T>) map.values();
    }

    public static <T> Collection<T> getNameList(Class<T> modelClazz) {
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        if (redisCache == null) {
            return null;
        }

        String key = new StringBuilder(modelClazz.getName()).append(CacheDataManager.CACHE_KEY_NAME_SPLIT).toString();
        Map<Object, Object> map = redisCache.getHashAll(CacheTypeEnum.BAS_DATA.getValue(), key);
        if (map == null) {
            return null;
        }

        return (Collection<T>) map.values();
    }

    /**
     * 获取Code
     *
     * @param modelClazz
     * @param id
     * @return
     */
    public static String getCode(Class<?> modelClazz, Long id) {
        if (id == null || modelClazz == null) {
            return null;
        }

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getNumber(modelClazz, id);
    }

    /**
     * 获取Code
     *
     * @param modelClass
     * @param id
     * @return
     */
    public static String getNumber(String modelClass, Long id) {
        if (id == null || StringUtils.isBlank(modelClass)) {
            return null;
        }
        Class<?> modelClazz = null;
        try {
            modelClazz = Class.forName(modelClass);
        } catch (Exception e) {
        }
        return getCode(modelClazz, id);
    }

    /**
     * 获取name
     *
     * @param modelClazz
     * @param id
     * @return
     */
    public static String getName(Class<?> modelClazz, Long id) {
        if (id == null || modelClazz == null) {
            return null;
        }

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getName(modelClazz, id);
    }

    /**
     * 获取name
     *
     * @param modelClass
     * @param id
     * @return
     */
    public static String getName(String modelClass, Long id) {
        if (id == null || StringUtils.isBlank(modelClass)) {
            return null;
        }
        Class<?> modelClazz = null;
        try {
            modelClazz = Class.forName(modelClass);
        } catch (Exception e) {
        }
        return getName(modelClazz, id);
    }

    /**
     * 获取指定属性缓存值
     *
     * @param modelClazz
     * @param propName
     * @param id
     * @return
     */
    public static String getProperty(Class<?> modelClazz, String propName, Long id) {
        if (modelClazz == null || propName == null || id == null) {
            return null;
        }

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getProperty(modelClazz, propName, id);
    }

    /**
     * 获取指定属性缓存值
     *
     * @param modelClass
     * @param propName
     * @param id
     * @return
     */
    public static String getProperty(String modelClass, String propName, Long id) {
        if (StringUtils.isBlank(modelClass) || propName == null || id == null) {
            return null;
        }
        Class<?> modelClazz = null;
        try {
            modelClazz = Class.forName(modelClass);
        } catch (Exception e) {
        }
        return getProperty(modelClazz, propName, id);
    }

    /**
     * 根据名称获取ID
     *
     * @param modelClazz
     * @param name
     * @return
     */
    public static Long getIdByName(Class<? extends Core> modelClazz, String name) {
        if (modelClazz == null || name == null) {
            return null;
        }

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getIdByName(modelClazz, name);
    }

    /**
     * 根据编码获取ID
     */
    public static Long getIdByName(String modelClass, String name) {
        if (StringUtils.isAnyBlank(modelClass, name)) {
            return null;
        }
        Class<? extends Core> modelClazz = null;
        try {
            modelClazz = (Class<? extends Core>) Class.forName(modelClass);
        } catch (Exception e) {
        }
        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getIdByName(modelClazz, name);
    }

    /**
     * 根据编码获取ID
     *
     * @param modelClazz
     * @param code
     * @return
     */
    public static Long getIdByNumber(Class<? extends Core> modelClazz, String code) {
        if (modelClazz == null || code == null) {
            return null;
        }
        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getIdByNumber(modelClazz, code);
    }

    /**
     * 根据编码获取ID
     */
    public static Long getIdByNumber(String modelClass, String code) {
        if (StringUtils.isAnyBlank(modelClass, code)) {
            return null;
        }
        Class<? extends Core> modelClazz = null;
        try {
            modelClazz = (Class<? extends Core>) Class.forName(modelClass);
        } catch (Exception e) {
        }
        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return null;
        }
        return cacheDataManager.getIdByNumber(modelClazz, code);
    }

    public static <D> void setNames(Class<?> modelClazz, List<D> list, String idCol, String nameCol) throws Exception {

        CacheDataManager cacheDataManager = (CacheDataManager) SpringUtil.getBean("cacheDataManager");
        if (cacheDataManager == null) {
            return;
        }
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        Method getIdMethod = list.get(0).getClass().getMethod("get" + StringUtils.firstAlpha2UpperCase(idCol));

        Method setNameMethod = list.get(0).getClass().getMethod("set" + StringUtils.firstAlpha2UpperCase(nameCol), String.class);
        setNameMethod.setAccessible(true);
        List<Long> ids = new ArrayList<>();
        for (Object a : list) {
            Long id = (Long) getIdMethod.invoke(a);
            if (id != null && !ids.contains(id)) {
                ids.add(id);
            }
        }
        // 获取 id -> name map
        Map<Long, String> nameMap = cacheDataManager.getNames(modelClazz, ids);
        // 根据map 设置列表名字字段
        for (Object a : list) {
            Long id = (Long) getIdMethod.invoke(a);
            if (id != null && nameMap.containsKey(id)) {
                setNameMethod.invoke(a, nameMap.get(id));
            }
        }

    }

    /**
     * 获取对象
     */
    public static Object getObjectByKey(String modelClass, CacheTypeEnum typeEnum, String key, String hashKey, String getUrl) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(hashKey) || typeEnum == null) {
            return null;
        }
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        if (redisCache == null) {
            return null;
        }
        Object object = redisCache.getHash(typeEnum.getValue(), key, hashKey);
        if (object == null) {
            // 没获取到 从服务中取
            Class<?> modelClazz = null;
            try {
                modelClazz = Class.forName(modelClass);
            } catch (Exception e) {
            }
            if (modelClazz == null) {
                return null;
            }
            try {
                if (StringUtils.isNotBlank(getUrl)) {
                    object = RestUtils.get(getUrl, (Map<String, String>)null, modelClazz);
                }
            } catch (Exception e) {
            }
            if (object != null) {
                cacheObjectByKey(typeEnum, key, hashKey, object);
            }
        }
        return object;
    }

    /**
     * 获取对象
     */
    public static Object getBaseDataByKey(String modelClass, String key, String hashKey, String getUrl) {
        return getObjectByKey(modelClass, CacheTypeEnum.BAS_DATA, key, hashKey, getUrl);
    }

    /**
     * 缓存对象值redis
     */
    public static void cacheObjectByKey(CacheTypeEnum typeEnum, String key, String hashKey, Object object) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(hashKey) || object == null || typeEnum == null) {
            return;
        }
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        if (redisCache == null) {
            return;
        }
        redisCache.putHash(typeEnum.getValue(), key, hashKey, object);
    }

    /**
     * 缓存对象值redis
     */
    public static void cacheBaseDataByKey(String key, String hashKey, Object object) {
        cacheObjectByKey(CacheTypeEnum.BAS_DATA, key, hashKey, object);
    }

    /**
     * 删除对象值redis
     */
    public static void removeObjectByKey(CacheTypeEnum typeEnum, String key, String hashKey) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(hashKey) || typeEnum == null) {
            return;
        }
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        if (redisCache == null) {
            return;
        }
        redisCache.removeHash(typeEnum.getValue(), key, hashKey);
    }

    /**
     * 删除对象值redis
     */
    public static void removeBaseDataByKey(String key, String hashKey) {
        removeObjectByKey(CacheTypeEnum.BAS_DATA, key, hashKey);
    }
}
